package com.hj.dapp.common.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.hj.dapp.business.role.model.Role;
import com.hj.dapp.business.user.model.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Base64;
import java.util.UUID;


/**
 * @author 胡奥程
 * @version 1.0
 * @date 2023/12/29
 */
public class JwtUtil {
    //PayLoad密钥
    private static final String JWT_PAYLOAD_USER_KEY = "HIDDEN";
    /**
     * 生成Token并设置过期时间（过期时间不在此处实现，在Redis中实现）
     * @param userInfo
     * @param privateKey
     * @return
     */
    public static String generateTokenExpireInMillis(Object userInfo, PrivateKey privateKey){
        return Jwts.builder()
                .claim(JWT_PAYLOAD_USER_KEY, JSON.toJSONString(userInfo))
                .setId(createJTI())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();

    }

    /**
     * Token解密
     * @param token
     * @param publicKey
     * @return
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey){
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    public static String getUserName(String token, PublicKey publicKey) {
        Jws<Claims> claimsJws = parserToken(token,publicKey);
        Claims body = claimsJws.getBody();
        User user = (User) JSON.parseObject(body.get(JWT_PAYLOAD_USER_KEY).toString(), User.class);
        return user.getUsername();
    }

    /**
     * 从Token中获取个人信息
     * @param token
     * @param publicKey
     * @param userType
     * @return
     * @param <T>
     */
    public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey, Class<T> userType){
        Jws<Claims> claimsJws = parserToken(token,publicKey);
        Claims body = claimsJws.getBody();
        Payload<T> claims = new Payload<>();
        claims.setId(body.getId());

        User user = (User) JSON.parseObject(body.get(JWT_PAYLOAD_USER_KEY).toString(), userType);
        ArrayList<Role> roles = new ArrayList<>();
        JSON.parseObject(body.get(JWT_PAYLOAD_USER_KEY).toString()).getJSONArray("roles").forEach(n->{
            JSONObject role = (JSONObject) n;
            Role r = new Role();
            //添加表达式前缀
            r.setName(role.getString("authority"));
            roles.add(r);

        });
        user.setRoles(roles);
        claims.setUserInfo((T) user);
        return claims;
    }


    /**
     * 生成ID
     * @return
     */
    private static String createJTI(){
        return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)));
    }

}
